package com.wigem.fa.service;

import cn.hutool.core.date.DateTime;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.wigem.approve.entity.DicReportEntity;
import com.wigem.approve.service.DicReportService;
import com.wigem.approve.service.GeApproveLogService;
import com.wigem.approve.vo.GeApproveLogVo;
import com.wigem.fa.dto.ApplyAndEntInfoDto;
import com.wigem.fa.dto.ApplySummaryDto;
import com.wigem.fa.entity.FaApplyEntity;
import com.wigem.fa.entity.FaApplyFileEntity;
import com.wigem.fa.entity.FaEntInfoEntity;
import com.wigem.fa.entity.ValidateFaApplyEntity;
import com.wigem.fa.mapper.FaApplyMapper;
import com.wigem.fa.mapper.FaEntInfoMapper;
import com.wigem.fa.vo.FaApplyFileVo;
import com.wigem.fa.vo.FaApplyVo;
import com.wigem.framework.common.pojo.PageResult;
import com.wigem.framework.common.util.common.FileUtils;
import com.wigem.framework.common.util.web.response.Result;
import com.wigem.framework.mybatis.core.query.LambdaQueryWrapperX;
import com.wigem.framework.sa.token.core.UserInfo;
import com.wigem.framework.sa.token.core.util.SaTokenUtils;
import com.wigem.module.general.entity.AssistNoticeEntity;
import com.wigem.module.general.mapper.AssistNoticeMapper;
import com.wigem.module.general.vo.AssistNoticeVo;
import com.wigem.system.entity.SystemAnnexEntity;
import com.wigem.system.service.SystemAnnexService;
import com.wigem.util.MappingResultUtils;
import com.wigem.util.StringUtils;
import com.wigem.util.ZipUtils;
import lombok.Data;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.util.ObjectUtils;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.IOException;
import java.lang.reflect.Field;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 企业申报Service业务层处理
 *
 * @author DH
 * @date 2024-10-20
 */
@Service
public class FaApplyServiceImpl implements FaApplyService {

    @Resource
    private FaApplyMapper faApplyMapper;
    @Resource
    private FaEntInfoMapper faEntInfoMapper;
    @Resource
    private DicReportService dicReportService;
    @Resource
    private GeApproveLogService approveLogService;

    @Resource
    private FaApplyFileService faApplyFileService;

    @Resource
    private AssistNoticeMapper assistNoticeMapper;

    @Resource
    private SystemAnnexService systemAnnexService;

    @Override
    public List<FaApplyEntity> getList(FaApplyVo faApplyvo) {

        return faApplyMapper.selectList(query(faApplyvo));
    }

    @Override
    public PageResult<FaApplyEntity> getPageList(FaApplyVo faApplyVo) {
        faApplyVo.setOrderColumn(MappingResultUtils.property2Field(faApplyVo.getOrderColumn(), FaApplyEntity.class));

        faApplyVo.setCreateUser(SaTokenUtils.getLoginUserInfo().getUserId());

        Page<FaApplyEntity> page = new Page<>(faApplyVo.getPageNo(), faApplyVo.getPageSize());
        IPage<FaApplyEntity> mappingList = faApplyMapper.getPageList(page, faApplyVo);
        return new PageResult<>(mappingList.getRecords(), mappingList.getTotal());

    }

    @Override
    public PageResult<AssistNoticeEntity> getNoticePageList(AssistNoticeVo vo) {
        vo.setOrderColumn(MappingResultUtils.property2Field(vo.getOrderColumn(), AssistNoticeEntity.class));
        Page<AssistNoticeEntity> page = new Page<>(vo.getPageNo(), vo.getPageSize());
        IPage<AssistNoticeEntity> mappingList = faApplyMapper.getNoticePageList(page, vo);
        return new PageResult<>(mappingList.getRecords(), mappingList.getTotal());

    }

    @Override
    public PageResult<ApplyAndEntInfoDto> getManagePageList(FaApplyVo faApplyVo) {
        faApplyVo.setOrderColumn(MappingResultUtils.property2Field(faApplyVo.getOrderColumn(), ApplyAndEntInfoDto.class));
        Page<ApplyAndEntInfoDto> page = new Page<>(faApplyVo.getPageNo(), faApplyVo.getPageSize());
        IPage<ApplyAndEntInfoDto> mappingList = faApplyMapper.getManagePageList(page, faApplyVo);
        return new PageResult<>(mappingList.getRecords(), mappingList.getTotal());
    }

    /**
     * 获取事中企业申报列表
     *
     * @param faApplyVo
     * @return
     */
    @Override
    public PageResult<ApplyAndEntInfoDto> getMidPageList(FaApplyVo faApplyVo) {
        faApplyVo.setOrderColumn(MappingResultUtils.property2Field(faApplyVo.getOrderColumn(), ApplyAndEntInfoDto.class));
        Page<ApplyAndEntInfoDto> page = new Page<>(faApplyVo.getPageNo(), faApplyVo.getPageSize());
        IPage<ApplyAndEntInfoDto> mappingList = faApplyMapper.getStagePageList(page, faApplyVo);
        return new PageResult<>(mappingList.getRecords(), mappingList.getTotal());
    }

    /**
     * 获取事后企业申报列表
     *
     * @param faApplyVo
     * @return
     */
    @Override
    public PageResult<ApplyAndEntInfoDto> getPostPageList(FaApplyVo faApplyVo) {
        faApplyVo.setOrderColumn(MappingResultUtils.property2Field(faApplyVo.getOrderColumn(), ApplyAndEntInfoDto.class));
        //事后状态
        faApplyVo.setStageId("3");
        Page<ApplyAndEntInfoDto> page = new Page<>(faApplyVo.getPageNo(), faApplyVo.getPageSize());
        IPage<ApplyAndEntInfoDto> mappingList = faApplyMapper.getStagePageList(page, faApplyVo);
        return new PageResult<>(mappingList.getRecords(), mappingList.getTotal());
    }

    @Override
    public PageResult<ApplySummaryDto> getSummaryPageList(FaApplyVo faApplyVo) {
        faApplyVo.setOrderColumn(MappingResultUtils.property2Field(faApplyVo.getOrderColumn(), ApplySummaryDto.class));
        Page<ApplySummaryDto> page = new Page<>(faApplyVo.getPageNo(), faApplyVo.getPageSize());
        IPage<ApplySummaryDto> mappingList = faApplyMapper.getSummaryPageList(page, faApplyVo);
        return new PageResult<>(mappingList.getRecords(), mappingList.getTotal());
    }

    @Override
    public ApplySummaryDto getTotalRow(FaApplyVo faApplyVo) {
        return faApplyMapper.getTotalRow(faApplyVo);
    }

    @Override
    public FaApplyEntity getEntity(String id) {
        return faApplyMapper.selectById(id);
    }
    @Override
    public Result back(String id) {
        //检查是否存在
        if (ObjectUtils.isEmpty(faApplyMapper.selectById(id))) {
            return Result.failure("企业申报不存在");
        }
        FaApplyEntity faApplyEntity = new FaApplyEntity();
        faApplyEntity.setId(id);
        faApplyEntity.setApproveId("0");

        int result = faApplyMapper.updateById(faApplyEntity);

        if (result > 0) {
            //新增审批日志
            UserInfo userInfo = SaTokenUtils.getLoginUserInfo();
            GeApproveLogVo approveLogVo = new GeApproveLogVo();
            approveLogVo.setUserId(userInfo.getUserId());
            approveLogVo.setRealName(userInfo.getRealName());
            approveLogVo.setUserUnit("管理员");
            approveLogVo.setOperateInfoId(id);
            approveLogVo.setOperateProcessName("管理员退回");
            approveLogVo.setOperateContent("管理员退回");
            approveLogVo.setOperateTime(new Date());
            approveLogService.save(approveLogVo);
        }

        return result > 0 ? Result.success("退回成功") : Result.failure("退回失败");
    }

    @Override
    public FaApplyEntity queryDto(FaApplyVo faApplyVo) {
        return faApplyMapper.queryDto(faApplyVo);
    }

    /**
     * 新增
     *
     * @param faApplyVo
     * @return
     */
    @Override
    public Result add(FaApplyVo faApplyVo) {
        //检查最新报告期是否开启
        if (ObjectUtils.isEmpty(dicReportService.getCurrentReportId("1"))) {
            return Result.failure("当前批次状态不允许操作", new FaApplyEntity());
        }

        // 创建 FaApplyEntity 对象并设置基本信息
        FaApplyEntity faApplyEntity = new FaApplyEntity();
        BeanUtils.copyProperties(faApplyVo, faApplyEntity);

        // 获取企业信息并设置
        setEntIdForFaApply(faApplyEntity);

        // 调用方法处理新增操作
        return createNewApplication(faApplyVo, faApplyEntity);
    }


    @Override
    public void update(FaApplyVo faApplyVo) {
        FaApplyEntity faApplyEntity = new FaApplyEntity();
        BeanUtils.copyProperties(faApplyVo, faApplyEntity);
        faApplyMapper.updateById(faApplyEntity);
    }

    /**
     * 保存
     *
     * @param faApplyVo
     * @return
     */
    @Override
    public Result save(FaApplyVo faApplyVo) {


        FaApplyEntity faApplyEntity = new FaApplyEntity();
        BeanUtils.copyProperties(faApplyVo, faApplyEntity);

        if (org.springframework.util.StringUtils.isEmpty(faApplyEntity.getId())) {
            // 新增操作
            return createNewApplication(faApplyVo, faApplyEntity);
        } else {
            // 编辑操作
            return updateExistingApplication(faApplyVo, faApplyEntity);
        }
    }

    /**
     * 新增保存信息
     *
     * @param faApplyVo
     * @param faApplyEntity
     * @return
     */
    private Result createNewApplication(FaApplyVo faApplyVo, FaApplyEntity faApplyEntity) {

        faApplyEntity.create();
        faApplyEntity.setRemoveMark("0");
        faApplyEntity.setApproveId("0"); // 未提交
        faApplyEntity.setStageId("1"); // 申报阶段

        //查询申报阶段的报告期id
        DicReportEntity reportByStageId = dicReportService.getCurrentReportId("1");
        faApplyEntity.setReportId(reportByStageId.getId());
        faApplyEntity.setReportYear(reportByStageId.getReportYear());

        faApplyEntity.setCreateUser(SaTokenUtils.getLoginUserInfo().getUserId());
        faApplyEntity.setCreateTime(new Date());
        faApplyMapper.insert(faApplyEntity);

        if (faApplyVo.getFileList() != null && !faApplyVo.getFileList().isEmpty()) {
            updateFile(faApplyEntity.getId(), faApplyVo, "1"); // 第一阶段：申报阶段
        }

        return Result.success("新增成功！", faApplyEntity);
    }


    /**
     * 设置企业ID
     *
     * @param faApplyEntity
     */
    private void setEntIdForFaApply(FaApplyEntity faApplyEntity) {
        FaEntInfoEntity faEntInfoEntity = faEntInfoMapper.getEntityByCreateUser(SaTokenUtils.getLoginUserInfo().getUserId());
        if (!ObjectUtils.isEmpty(faEntInfoEntity)) {
            faApplyEntity.setEntId(faEntInfoEntity.getId());
        }
    }

    /**
     * 更新保存已有的申报信息
     *
     * @param faApplyVo
     * @param faApplyEntity
     * @return
     */
    private Result updateExistingApplication(FaApplyVo faApplyVo, FaApplyEntity faApplyEntity) {
        // 检查当前记录的状态
        FaApplyEntity checkStatus = faApplyMapper.getEntity(faApplyEntity.getId());
        String stageId = checkStatus.getStageId();
        String approveId = getApproveIdByStage(stageId, checkStatus);

        // 判断是否可以编辑
        if (!canEdit(approveId)) {
            return Result.failure("无法编辑已提交的信息！");
        }

        // 根据阶段更新文件
        List<FaApplyFileVo> fileList = getFileListByStage(faApplyVo, stageId);
        if (fileList != null && !fileList.isEmpty()) {
            updateFile(faApplyEntity.getId(), faApplyVo, stageId);
        }

        faApplyMapper.updateById(faApplyEntity);
        return Result.success("保存成功！");
    }

    /**
     * 根据阶段 ID 获取对应的审批 ID
     *
     * @param stageId
     * @param checkStatus
     * @return
     */
    private String getApproveIdByStage(String stageId, FaApplyEntity checkStatus) {
        switch (stageId) {
            case "1": // 申报阶段
                return checkStatus.getApproveId();
            case "2": // 事中阶段
                return checkStatus.getMidStageApproveId();
            case "3": // 事后阶段
                return checkStatus.getPostStageApproveId();
            default:
                throw new IllegalStateException("未知的阶段ID: " + stageId);
        }
    }

    /**
     * 判断能否编辑
     *
     * @param approveId
     * @return
     */
    private boolean canEdit(String approveId) {
        return "0".equals(approveId) || "2".equals(approveId); // 只有未提交或退回修改的状态可以编辑
    }

    /**
     * 更新申报文件
     *
     * @param applyId
     * @param faApplyVo
     * @param stageId
     */
    private void updateFile(String applyId, FaApplyVo faApplyVo, String stageId) {
        // 检查阶段 ID 是否有效
        if (stageId == null || !Arrays.asList("1", "2", "3").contains(stageId)) {
            throw new IllegalArgumentException("无效的阶段ID: " + stageId);
        }

        // 根据阶段 ID 删除所有附件
        FaApplyFileEntity faApplyFileentity = new FaApplyFileEntity();
        faApplyFileentity.setApplyId(applyId);
        faApplyFileentity.setStageId(stageId);

        faApplyFileService.deleteAllByApplyId(faApplyFileentity);

        // 定义一个映射来管理不同阶段对应的文件列表
        List<FaApplyFileVo> fileList = getFileListByStage(faApplyVo, stageId);

        // 如果该阶段有文件列表，插入文件
        if (fileList != null && !fileList.isEmpty()) {
            for (FaApplyFileVo newFile : fileList) {
                newFile.setApplyId(applyId);
                newFile.setStageId(stageId);
                newFile.setPolicyType(faApplyVo.getPolicyType());
                faApplyFileService.add(newFile);
            }
        }

    }

    /**
     * 提取出获取文件列表的逻辑
     */
    private List<FaApplyFileVo> getFileListByStage(FaApplyVo faApplyVo, String stageId) {
        switch (stageId) {
            case "1":
                return faApplyVo.getFileList();
            case "2":
                return faApplyVo.getMidStageFileList();
            case "3":
                return faApplyVo.getPostStageFileList();
            default:
                return Collections.emptyList(); // 无效的 stageId 时返回空列表
        }
    }

    /**
     * 提交
     *
     * @param faApplyVo
     * @return
     */
    @Override
    public Result commit(FaApplyVo faApplyVo) {

        // 判断当前提交的申报信息是否保存过
        if (StringUtils.isEmpty(faApplyVo.getId())) {
            return Result.failure("请先保存申报信息后再提交！");
        }

        // 根据id获取当前申报信息
        FaApplyEntity entity = faApplyMapper.getEntity(faApplyVo.getId());
        String stageId = entity.getStageId();

        //判断没提交过得就不让提交了（临时）
//        if (entity.getSubmitTime().equals(null)) {
//            return Result.failure("当前申报信息状态不可提交！");
//        }

        // 获取阶段名称
        String stageName = getStageName(stageId);
        if (stageName == null) {
            return Result.failure("未知的阶段ID，无法提交！");
        }

        // 处理不同阶段的提交逻辑，变更提交状态
        Result validationResult = validateForStage(faApplyVo, entity, stageId);
        if (!validationResult.isSuccess()) {
            return validationResult;
        }

        // 插入对应stage阶段的附件
        List<FaApplyFileVo> fileList = getFileListByStage(faApplyVo, stageId);
        if (fileList != null && !fileList.isEmpty()) {
            updateFile(entity.getId(), faApplyVo, stageId);
        }

        // 获取当前登录用户信息并设置提交时间和提交人
        UserInfo userInfo = SaTokenUtils.getLoginUserInfo();
        setSubmitDetails(faApplyVo, userInfo);

        // 保存数据
        Result result = this.save(faApplyVo);
        if (result.isSuccess()) {
            result.setMsg("提交成功！");
            logApprovalAction(userInfo, faApplyVo.getId(), stageName);
        }

        return result;
    }

    @Override
    public Result postPoneSubmit(FaApplyVo faApplyvo) {
        try {
            // 检查传入的 FaApplyVo 对象是否为空
            if (faApplyvo == null) {
                return Result.failure("提交失败！");
            }

            // 检查关键属性是否为空
            if (StringUtils.isEmpty(faApplyvo.getId()) ||
                    faApplyvo.getPostPoneSubmitTime() == null ||
                    faApplyvo.getPostPoneEndTime() == null ||
                    StringUtils.isEmpty(faApplyvo.getPostPoneFileId())) {
                return Result.failure("提交失败！");
            }

            // 查询当前申报信息
            FaApplyEntity entity = faApplyMapper.getEntity(faApplyvo.getId());

            // 判断当前申报信息状态是否可延期提交
            if (!"3".equals(entity.getStageId())) {
                return Result.failure("当前申报信息状态不可申请延期！");
            }

            // 构建延期申请实体
            FaApplyEntity faApplyEntity = buildPostPoneEntity(faApplyvo);

            int result = faApplyMapper.updateById(faApplyEntity);

            return result > 0 ? Result.success("延期提交成功！") : Result.failure("延期提交失败，请稍后重试！");
        } catch (Exception e) {
            return Result.failure("提交失败！");
        }
    }

    /**
     * 构建延期申请实体
     *
     * @param faApplyvo 企业申报信息对象
     * @return 构建好的 FaApplyEntity 对象
     */
    private FaApplyEntity buildPostPoneEntity(FaApplyVo faApplyvo) {
        FaApplyEntity faApplyEntity = new FaApplyEntity();
        faApplyEntity.setId(faApplyvo.getId());
        faApplyEntity.setPostPoneCreateTime(new Date());
        faApplyEntity.setPostPoneSubmitTime(faApplyvo.getPostPoneSubmitTime());
        faApplyEntity.setPostPoneEndTime(faApplyvo.getPostPoneEndTime());
        faApplyEntity.setPostPoneFileId(faApplyvo.getPostPoneFileId());
        faApplyEntity.setPostPoneStatus("1");
        return faApplyEntity;
    }

    /**
     * 获取阶段名称
     */
    private String getStageName(String stageId) {
        Map<String, String> stageMap = new HashMap<>();
        stageMap.put("1", "申报阶段");
        stageMap.put("2", "事中阶段");
        stageMap.put("3", "事后阶段");

        return stageMap.get(stageId);
    }

    /**
     * 设置提交时间和提交人
     */
    private void setSubmitDetails(FaApplyVo faApplyVo, UserInfo userInfo) {
        faApplyVo.setSubmitTime(new Date());
        faApplyVo.setSubmitUser(userInfo.getUserId());
    }

    /**
     * 验证不同阶段的提交逻辑
     */
    private Result validateForStage(FaApplyVo faApplyVo, FaApplyEntity entity, String stageId) {
        switch (stageId) {
            case "1": // 申报阶段
                return validateForDeclarationStage(faApplyVo, entity);
            case "2": // 事中阶段
                faApplyVo.setMidStageSubmitTime(DateTime.now());
                faApplyVo.setMidStageApproveId("1"); //设置为已提交状态
                return Result.success();
            case "3": // 事后阶段
                faApplyVo.setPostStageSubmitTime(DateTime.now());
                faApplyVo.setPostStageApproveId("1"); //设置为已提交状态
                return Result.success();
            default:
                return Result.failure("未知的阶段ID，无法提交！");
        }
    }

    /**
     * 验证申报阶段的必填字段
     */
    private Result validateForDeclarationStage(FaApplyVo faApplyVo, FaApplyEntity entity) {
        ValidateFaApplyEntity faApplyEntity = new ValidateFaApplyEntity();
        BeanUtils.copyProperties(faApplyVo, faApplyEntity);

        Result validateFaApplyEntityIsNotEmpty = this.validateFaApplyEntityIsNotEmpty(faApplyEntity);
        if (!validateFaApplyEntityIsNotEmpty.isSuccess()) {
            return validateFaApplyEntityIsNotEmpty;
        }
        // 验证同一申报批次下是否已提交过相同的申报类型
        Result validateSamePolicyType = validateSamePolicyType(entity.getReportId(), entity.getPolicyType(), entity.getEntId());
        if (!validateSamePolicyType.isSuccess()) {
            return validateSamePolicyType;
        }
        faApplyVo.setApproveId("1"); // 设置为已提交状态
        return Result.success();
    }

    /**
     * 验证同一申报批次下是否已提交过相同的申报类型
     *
     * @param reportId
     * @param policyType
     * @param entId
     * @return
     */
    private Result validateSamePolicyType(String reportId, String policyType, String entId) {
        FaApplyVo vo = new FaApplyVo();
        vo.setReportId(reportId);
        vo.setPolicyType(policyType);
        vo.setEntId(entId);
        List<FaApplyEntity> list = faApplyMapper.getEnterpriseSamePolicyType(vo);
        if (list.size() > 0) {
            return Result.failure("当前申报批次您已提交过相同的申报类型，无法重复提交！");
        } else {
            return Result.success();
        }
    }

    /**
     * 记录提交日志
     */
    private void logApprovalAction(UserInfo userInfo, String faApplyId, String stageName) {
        GeApproveLogVo approveLogVo = new GeApproveLogVo();
        approveLogVo.setUserId(userInfo.getUserId());
        approveLogVo.setRealName(userInfo.getRealName());
        approveLogVo.setUserUnit("企业");
        approveLogVo.setOperateInfoId(faApplyId);
        approveLogVo.setOperateProcessName(stageName + "提交");
        approveLogVo.setOperateContent(stageName + "提交");
        approveLogVo.setOperateTime(new Date());
        approveLogService.save(approveLogVo);
    }


    /**
     * 验证企业申报信息是否为空
     *
     * @param entity
     * @return
     */
    private Result validateFaApplyEntityIsNotEmpty(ValidateFaApplyEntity entity) {
        Field[] fields = ValidateFaApplyEntity.class.getDeclaredFields();
        for (Field field : fields) {
            field.setAccessible(true); // 设置可访问性，以便可以访问私有属性
            try {
                // 获取属性值
                Object propertyValue = field.get(entity);
                if (("" + propertyValue).isEmpty() || propertyValue == null) {
                    return Result.failure("请完善企业信息，如信息已全部填写请检查是否已保存！");
                }
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            }
        }
        return Result.success();
    }

    /**
     * 审批操作
     *
     * @param faApplyVo
     * @return
     */
    @Override
    public Result approve(FaApplyVo faApplyVo) {
        FaApplyEntity entity = faApplyMapper.getEntity(faApplyVo.getId());
        String stageId = entity.getStageId();
        String stageName = getStageName(stageId);

        String nextApproveId = faApplyVo.getNextApproveId();
        String content = "";

        // 根据stage，返回能够审批{"1":["1,"3"],"2":["1"],"3":["1"]}
        List<String> allowedApproveIds = getAllowedApproveIdsByStage(stageId);

        // 判断当前申报信息状态是否可审批
        if (!allowedApproveIds.contains(getApproveIdByStage(stageId, entity))) {
            return Result.failure("当前申报信息状态不可审批！");
        }
        //  判断是否选择审批操作
        if (nextApproveId == null || nextApproveId.isEmpty()) {
            return Result.failure("请选择审批操作！");
        }

        FaApplyEntity faApplyEntity = new FaApplyEntity();
        faApplyEntity.setId(faApplyVo.getId());

        //判断是否要修改stageId，移动下一个阶段
        updateStageIdBasedOnApproval(faApplyEntity, stageId, nextApproveId);

        switch (stageId) {
            case "1": // 申报阶段
                content = handleInitialApproval(entity, faApplyVo);
                //判断通过，保存资金
                if ("5".equals(nextApproveId)) {
                    faApplyEntity.setFinalFund(faApplyVo.getFinalFund());
                }
                faApplyEntity.setApproveId(nextApproveId);
                break;
            case "2": // 事中阶段
                ApproveResult resultStage2 = handleMidStageApproval(entity, faApplyVo);
                faApplyEntity.setMidStageApproveId(nextApproveId);
                faApplyEntity.setMidStageExpertOpinionFileId(resultStage2.expertOpinionFileId);
                content = resultStage2.getContent();
                //判断通过
                if ("3".equals(nextApproveId)) {
                    faApplyEntity.setMidStageExpertOpinionId(resultStage2.getExpertOpinionId());
                    faApplyEntity.setMidStageExpertOpinion(resultStage2.getExpertOpinion());
                }
                break;
            case "3": // 事后阶段
                ApproveResult resultStage3 = handlePostStageApproval(entity, faApplyVo);
                faApplyEntity.setPostStageApproveId(nextApproveId);
                faApplyEntity.setPostStageExpertOpinionFileId(resultStage3.expertOpinionFileId);
                content = resultStage3.getContent();
                //判断通过
                if ("3".equals(nextApproveId)) {
                    faApplyEntity.setPostStageExpertOpinionId(resultStage3.getExpertOpinionId());
                    faApplyEntity.setPostStageExpertOpinion(resultStage3.getExpertOpinion());
                }
                break;
            default:
                return Result.failure("无效的审批阶段！");
        }
        int updateSize = faApplyMapper.updateById(faApplyEntity);
        UserInfo userInfo = SaTokenUtils.getLoginUserInfo();
        //新增审批日志
        if (updateSize > 0) {
            logApproval(faApplyVo, userInfo, content, stageName);
            return Result.success(content);
        } else {
            return Result.failure(content);
        }
    }

    private List<String> getAllowedApproveIdsByStage(String stageId) {
        switch (stageId) {
            case "1":
                return Arrays.asList("1", "3"); // 申报阶段
            case "2":
            case "3":
                return Collections.singletonList("1"); // 事中阶段 & 事后阶段
            default:
                return Collections.emptyList();
        }
    }

    /**
     * 判断是否要移动下一个stage
     *
     * @param faApplyEntity
     * @param stageId
     * @param nextApproveId
     */
    private void updateStageIdBasedOnApproval(FaApplyEntity faApplyEntity, String stageId, String nextApproveId) {
        switch (stageId) {
            case "1": // 申报阶段
                if ("5".equals(nextApproveId)) {
                    faApplyEntity.setStageId("2"); // Move to "事中阶段"
                }
                break;
            case "2": // 事中阶段
                if ("3".equals(nextApproveId)) {
                    faApplyEntity.setStageId("3"); // Move to "事后阶段"
                }
                break;
            case "3": // 事后阶段
                if ("3".equals(nextApproveId)) {
                    faApplyEntity.setStageId("4"); // Move to "归档"
                }
                break;
            default:
                break;
        }
    }

    //申报阶段审核
    private String handleInitialApproval(FaApplyEntity entity, FaApplyVo faApplyVo) {
        String nextApproveId = faApplyVo.getNextApproveId();
        String content = "";

        switch (entity.getApproveId()) {
            case "1": // 初审
                content = handleInitialReview(nextApproveId, faApplyVo);
                break;
            case "3": // 复审
                content = handleReexamination(nextApproveId, faApplyVo);

                break;
            default:
                return "无效的初审操作！";
        }
        return content;
    }

    // 初审审核不同操作对应的内容
    private String handleInitialReview(String nextApproveId, FaApplyVo faApplyVo) {
        switch (nextApproveId) {
            case "2":
                return "初审退回修改，原因：" + faApplyVo.getReasonForReturn();
            case "3":
                return "初审通过未终审，原因：" + faApplyVo.getReasonForReturn();
            case "4":
                return "初审不通过，原因：" + faApplyVo.getReasonForReturn();
            default:
                return "无效的初审操作！";
        }
    }

    //复审审核不同操作对应的内容
    private String handleReexamination(String nextApproveId, FaApplyVo faApplyVo) {
        switch (nextApproveId) {
            case "5":
                return "终审通过，审批金额：" + faApplyVo.getFinalFund() + "万元";
            case "6":
                return "终审不通过，原因：" + faApplyVo.getReasonForReturn();
            default:
                return "无效的初审操作！";
        }
    }

    //事中阶段审核
    private ApproveResult handleMidStageApproval(FaApplyEntity entity, FaApplyVo faApplyVo) {
        String nextApproveId = faApplyVo.getNextApproveId();
        switch (entity.getMidStageApproveId()) {
            case "1": // 事中审批
                return handleMidStage(nextApproveId, faApplyVo);
            default:
                ApproveResult result = new ApproveResult();
                result.setContent("无效的审批状态！");
                return result;
        }
    }

    //事中阶段审核不同操作对应的内容
    private ApproveResult handleMidStage(String nextApproveId, FaApplyVo faApplyVo) {
        ApproveResult result = new ApproveResult();
        result.setCode(nextApproveId);
        switch (nextApproveId) {
            case "2":
                result.setContent("退回修改，原因：" + faApplyVo.getReasonForReturn());
                break;
            case "3":
                result.setExpertOpinionId(faApplyVo.getMidStageExpertOpinionId());
                result.setExpertOpinion(faApplyVo.getMidStageExpertOpinion());
                result.setExpertOpinionFileId(faApplyVo.getMidStageExpertOpinionFileId());
                result.setContent("通过");
                break;
            default:
                result.setContent("无效的初审操作!");
                break;
        }
        return result;
    }

    //事后阶段审核
    private ApproveResult handlePostStageApproval(FaApplyEntity entity, FaApplyVo faApplyVo) {
        String nextApproveId = faApplyVo.getNextApproveId();
        switch (entity.getPostStageApproveId()) {
            case "1": // 事后审批
                return handlePostStage(nextApproveId, faApplyVo);
            default:
                ApproveResult result = new ApproveResult();
                result.setContent("无效的审批状态！");
                return result;
        }
    }

    //事后阶段审核不同操作对应的内容
    private ApproveResult handlePostStage(String nextApproveId, FaApplyVo faApplyVo) {
        ApproveResult result = new ApproveResult();
        result.setCode(nextApproveId);
        switch (nextApproveId) {
            case "2":
                result.setContent("退回修改，原因：" + faApplyVo.getReasonForReturn());
                break;
            case "3":
                result.setExpertOpinionId(faApplyVo.getPostStageExpertOpinionId());
                result.setExpertOpinion(faApplyVo.getPostStageExpertOpinion());
                result.setExpertOpinionFileId(faApplyVo.getPostStageExpertOpinionFileId());
                break;
            default:
                result.setContent("无效的初审操作!");
                break;
        }
        return result;
    }

    //审核日志
    private void logApproval(FaApplyVo faApplyVo, UserInfo userInfo, String content, String stageName) {
        GeApproveLogVo approveLogVo = new GeApproveLogVo();
        approveLogVo.setUserId(userInfo.getUserId());
        approveLogVo.setRealName(userInfo.getRealName());
        approveLogVo.setUserUnit(userInfo.getRealName());
        approveLogVo.setOperateInfoId(faApplyVo.getId());
        approveLogVo.setOperateProcessName(stageName + "审核");
        approveLogVo.setOperateContent(content);
        approveLogVo.setOperateTime(new Date());
        approveLogService.save(approveLogVo);
    }

    @Override
    public int delete(String id) {
        return faApplyMapper.deleteById(id);
    }


    @Override
    public int remove(String id) {
        return faApplyMapper.remove(id);
    }

    @Override
    public Result noticeSave(AssistNoticeVo vo) {
        AssistNoticeEntity assistNoticeEntity = new AssistNoticeEntity();
        BeanUtils.copyProperties(vo, assistNoticeEntity);
        if (org.springframework.util.StringUtils.isEmpty(vo.getNoticeId())) {
            assistNoticeEntity.create();
            assistNoticeMapper.insert(assistNoticeEntity);
        } else {
            assistNoticeMapper.updateById(assistNoticeEntity);
        }
        return Result.success("保存成功！");
    }

    public LambdaQueryWrapperX<FaApplyEntity> query(FaApplyVo faApplyVo) {

        LambdaQueryWrapperX<FaApplyEntity> faApplyEntityLambdaQueryWrapperX = new LambdaQueryWrapperX<>();
        faApplyEntityLambdaQueryWrapperX = faApplyEntityLambdaQueryWrapperX
                .eqIfPresent(FaApplyEntity::getId, faApplyVo.getId())
                .likeIfPresent(FaApplyEntity::getProjectName, faApplyVo.getProjectName())
                .eqIfPresent(FaApplyEntity::getEntId, faApplyVo.getEntId())
                .eqIfPresent(FaApplyEntity::getReportId, faApplyVo.getReportId())
                .eqIfPresent(FaApplyEntity::getPolicyType, faApplyVo.getPolicyType())
                .eqIfPresent(FaApplyEntity::getCreateTime, faApplyVo.getCreateTime())
                .eqIfPresent(FaApplyEntity::getCreateUser, faApplyVo.getCreateUser())
                .eqIfPresent(FaApplyEntity::getSubmitTime, faApplyVo.getSubmitTime())
                .eqIfPresent(FaApplyEntity::getSubmitUser, faApplyVo.getSubmitUser())
                .eqIfPresent(FaApplyEntity::getApproveId, faApplyVo.getApproveId())
                .eqIfPresent(FaApplyEntity::getRemoveMark, faApplyVo.getRemoveMark())
                .eqIfPresent(FaApplyEntity::getProjectIntroduction, faApplyVo.getProjectIntroduction())
                .eqIfPresent(FaApplyEntity::getProposalFund, faApplyVo.getProposalFund())
                .eqIfPresent(FaApplyEntity::getReportYear, faApplyVo.getReportYear())
                .eqIfPresent(FaApplyEntity::getLastYearSalesRevenue, faApplyVo.getLastYearSalesRevenue())
                .eqIfPresent(FaApplyEntity::getLastYearTax, faApplyVo.getLastYearTax())
                .eqIfPresent(FaApplyEntity::getLastYearProfit, faApplyVo.getLastYearProfit())
                .eqIfPresent(FaApplyEntity::getBeforeLastYearSalesRevenue, faApplyVo.getBeforeLastYearSalesRevenue())
                .eqIfPresent(FaApplyEntity::getBeforeLastYearTax, faApplyVo.getBeforeLastYearTax())
                .eqIfPresent(FaApplyEntity::getBeforeLastYearProfit, faApplyVo.getBeforeLastYearProfit())
                .eqIfPresent(FaApplyEntity::getLastYearBusinessRevenueGrowthRate, faApplyVo.getLastYearBusinessRevenueGrowthRate())
                .eqIfPresent(FaApplyEntity::getRdPersonProportion, faApplyVo.getRdPersonProportion())
                .eqIfPresent(FaApplyEntity::getPastThreeYearPatentAcceptCount, faApplyVo.getPastThreeYearPatentAcceptCount())
                .eqIfPresent(FaApplyEntity::getPastThreeYearLicenseCount, faApplyVo.getPastThreeYearLicenseCount())
                .eqIfPresent(FaApplyEntity::getPastThreeYearCopyrightCount, faApplyVo.getPastThreeYearCopyrightCount())
                .eqIfPresent(FaApplyEntity::getPastThreeYearTrademarksCount, faApplyVo.getPastThreeYearTrademarksCount())
                .eqIfPresent(FaApplyEntity::getIntellectualPropertyRightsCount, faApplyVo.getIntellectualPropertyRightsCount())
                .eqIfPresent(FaApplyEntity::getPastThreeYearProjectsSupportedCount, faApplyVo.getPastThreeYearProjectsSupportedCount())
                .eqIfPresent(FaApplyEntity::getFileId, faApplyVo.getFileId())

        ;
        return faApplyEntityLambdaQueryWrapperX;
    }

    /**
     * 事中阶段审核结果
     *
     * @return
     */
    @Data
    class ApproveResult {

        //状态code
        private String code;

        //进度情况
        private String expertOpinionId;

        //专家意见
        private String expertOpinion;

        //专家意见附件
        private String expertOpinionFileId;

        //返回结果
        private String content;
    }

    private HashMap<String, String> policyType1 = new HashMap<String, String>() {{
        put("1", "营业执照扫描件（加盖公章）");
        put("2", "可说明企业统计关系的证明文件");
        put("3", "申报单位上年度财务审计报告");
        put("4", "申报单位上年度完税证明");
        put("5", "朝阳区科技计划项目申报书及预算表（附件3-01）（盖章）");
        put("6", "科技总部生态体系建设计划书");
        put("7", "项目配套经费来源说明");
        put("8", "有效知识产权清单及证明文件（包括PCT国际专利、国内专利证书、计算机软件著作权证书等）");
        put("9", "承诺书（附件2）（签字盖章）");
        put("10", "其他有助于立项的证明材料");
        put("11", "朝阳区科技计划项目汇总表（附件3-00方向1）（Excel原格式）");
    }};
    private HashMap<String, String> policyType2 = new HashMap<String, String>() {{
        put("1", "营业执照扫描件（加盖公章）");
        put("2", "可说明企业统计关系的证明文件");
        put("3", "申报单位上年度财务审计报告");
        put("4", "申报单位上年度完税证明");
        put("5", "朝阳区科技计划项目申报书及预算表（附件3-01）（盖章）");
        put("6", "研究开发项目计划书");
        put("7", "项目配套经费来源说明");
        put("8", "有效知识产权清单及证明文件（包括PCT国际专利、国内专利证书、计算机软件著作权证书等）");
        put("9", "承诺书（附件2）（签字盖章）");
        put("10", "其他有助于立项的证明材料");
        put("11", "朝阳区科技计划项目汇总表（附件3-00方向1）（Excel原格式）");
    }};
    private HashMap<String, String> policyType3 = new HashMap<String, String>() {{
        put("1", "营业执照扫描件（加盖公章）");
        put("2", "可说明企业统计关系的证明文件");
        put("3", "申报单位上年度财务审计报告");
        put("4", "申报单位上年度完税证明");
        put("5", "朝阳区科技计划项目申报书及预算表（附件3-01）（盖章）");
        put("6", "研究开发项目计划书");
        put("7", "项目配套经费来源说明");
        put("8", "与京津冀三地高校、科研院所协同创新合同及协同创新项目证明文件");
        put("9", "有效知识产权清单及证明文件");
        put("10", "承诺书（附件2）（签字盖章）");
        put("11", "其他有助于立项的证明材料");
        put("12", "朝阳区科技计划项目汇总表（附件3-00方向3）（Excel原格式）");
    }};
    private HashMap<String, String> policyType4 = new HashMap<String, String>() {{
        put("1", "营业执照扫描件（加盖公章）");
        put("2", "可说明企业统计关系的证明文件（若企业为当年新注册则提供单位行业代码、营业活动、单位性质说明加盖公章）");
        put("8", "申报单位上年度财务审计报告");
        put("3", "申报单位上年度完税证明");
        put("4", "朝阳区科技计划项目申报书及预算表（附件3-04）（盖章）");
        put("5", "社会发展科技创新项目计划书");
        put("7", "其他有助于立项的证明材料");
        put("6", "承诺书（附件2）（签字盖章）");
        put("9", "朝阳区科技计划项目汇总表（附件3-00方向4）（Excel原格式）");
    }};

    private HashMap<String, String> policyType5 = new HashMap<String, String>() {{
        put("1", "营业执照扫描件（加盖公章）");
        put("2", "可说明企业统计关系的证明文件（若企业为当年新注册则提供单位行业代码、营业活动、单位性质说明加盖公章）");
        put("12", "申报单位上年度财务审计报告");
        put("3", "申报单位上年度完税证明");
        put("4", "朝阳区科技计划项目申报书及预算表（附件3-05）（盖章）");
        put("5", "申报单位运营情况简介说明及相关证明材料");
        put("6", "服务企业（机构）组织科技服务活动证明材料（如有，请提供活动明细表、活动课件、现场活动照片、线上会议截图等）");
        put("7", "对区域或行业的示范带动作用的证明材料（如有，请提供服务政府或行业龙头企业的合同/协议、主持或参与制（修）订的相关标准等）");
        put("8", "关于企业诚信度、知名度、美誉度的盖章说明及证明材料（如有，请提供上年度客户满意度调查表、行业报道、荣誉资质等）");
        put("9", "办公场所房屋产权证明或租赁合同");
        put("11", "其他有助于立项的证明材料");
        put("10", "承诺书（附件2）（签字盖章）");
        put("13", "朝阳区科技计划项目汇总表（附件3-00方向5）（Excel原格式）");
    }};

    private HashMap<String, String> policyType6 = new HashMap<String, String>() {{
        put("1", "营业执照扫描件（加盖公章）");
        put("2", "可说明企业统计关系的证明文件（若企业为当年新注册则提供单位行业代码、营业活动、单位性质说明加盖公章）");
        put("10", "申报单位上年度财务审计报告");
        put("3", "申报单位上年度完税证明");
        put("4", "朝阳区科技计划项目申报书及预算表（附件3-06）（盖章）");
        put("5", "研究开发项目计划书");
        put("6", "项目配套经费来源说明");
        put("7", "申报单位以往项目结项报告以及承担项目情况说明");
        put("9", "其他有助于立项的证明材料");
        put("8", "承诺书（附件2）（签字盖章）");
        put("11", "朝阳区科技计划项目汇总表（附件3-00方向6）（Excel原格式）");
    }};

    private HashMap<String, String> policyType7 = new HashMap<String, String>() {{
        put("1", "营业执照扫描件（加盖公章）");
        put("7", "申报单位上年度财务审计报告");
        put("2", "朝阳区科技计划项目申报书及预算表（附件3-07）（盖章）");
        put("3", "活动策划书");
        put("4", "项目承担单位承担活动能力情况介绍（申报单位以往举办活动案例清单、计划方案报告、产生社会效益情况、产生经济效益情况等（盖章）");
        put("6", "其他有助于立项的证明材料");
        put("5", "承诺书（附件2）（签字盖章）");
        put("8", "朝阳区科技计划项目汇总表（附件3-00方向7）（Excel原格式）");
    }};
    private HashMap<String, String> policyType8 = new HashMap<String, String>() {{
        put("1", "申报材料");
    }};

    @Override
    public void exportApply(HttpServletResponse response, FaApplyVo faApplyVo) throws Exception {
        FaApplyEntity applyEntity = faApplyMapper.getEntity(faApplyVo.getId());

        String filePath = "/www/static/enterpriseDeclare/" + faApplyVo.getOrgName();

        List<FaApplyFileEntity> fileList = faApplyFileService.getListByApplyId(applyEntity.getId());
        List<FaApplyFileEntity> fileListResult = fileList.stream().filter(fileEntity -> fileEntity.getStageId().equals("1")).collect(Collectors.toList());
        //创建企业名称文件夹
        ZipUtils.createFile(filePath);
        //循环创建临时文件夹并将附件copy到文件夹下
        String policyType = applyEntity.getPolicyType();
        HashMap<String, String> policyTypeFileNameList = new HashMap<String, String>();
        //获取方向文件列表
        switch (policyType) {
            case "1":
                policyTypeFileNameList = policyType1;
                break;
            case "2":
                policyTypeFileNameList = policyType2;
                break;
            case "3":
                policyTypeFileNameList = policyType3;
                break;
            case "4":
                policyTypeFileNameList = policyType4;
                break;
            case "5":
                policyTypeFileNameList = policyType5;
                break;
            case "6":
                policyTypeFileNameList = policyType6;
                break;
            case "7":
                policyTypeFileNameList = policyType7;
                break;
            case "8":
                policyTypeFileNameList = policyType8;
                break;
        }

        //获取企业所有附件
        List<String> annexFolderIdList = new ArrayList<>();
        for (FaApplyFileEntity fileEntity : fileListResult) {
            if (fileEntity.getFileId() != null) {
                annexFolderIdList.add(fileEntity.getFileId());
            }
        }
        List<SystemAnnexEntity> annexList = systemAnnexService.getBatchListByFolderId(annexFolderIdList);


        //处理企业所有的附件
        for (Map.Entry<String, String> entry : policyTypeFileNameList.entrySet()) {
            for (FaApplyFileEntity fileEntity : fileListResult) {
                //创建临时文件
                String itemFilePathParent = filePath + "/" + entry.getValue();
                if (fileEntity.getFileNo().equals(entry.getKey())) {
                    Optional<SystemAnnexEntity> optionalAnnex = annexList.stream().filter(annex -> fileEntity.getFileId().equals(annex.getFolderId())).findFirst();
                    if (optionalAnnex.isPresent()) {
                        SystemAnnexEntity firstMatchingAnnex = optionalAnnex.get();
                        ZipUtils.createFile(itemFilePathParent);
                        // 处理第一个匹配的对象
                        String itemFilePath = itemFilePathParent + "/" + firstMatchingAnnex.getFileName();
                        File sourceFile = new File(firstMatchingAnnex.getFilePath());
                        File destinationFile = new File(itemFilePath);
                        try {
                            ZipUtils.copyFile(sourceFile, destinationFile);
                        } catch (IOException e) {
                            throw new RuntimeException(e);
                        }
                    }
                }
            }
        }

        String outPath = filePath + ".zip";
        //压缩文件
        ZipUtils.zipFolder(filePath, outPath);

        //下载文件
        FileUtils.downLoad(response, outPath, applyEntity.getOrgName() + ".zip");
    }
}
